import datetime

from django.http import StreamingHttpResponse
from django.utils.encoding import escape_uri_path
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import viewsets, mixins
from rest_framework.decorators import api_view
from rest_framework.filters import SearchFilter, OrderingFilter
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated

from celery.result import AsyncResult

from .models import Tasks
from .tasks import *
from .serializers import TasksSerializer
from export.create_zip import create_zip


# class ReturnMsg:
#     """
#     定义返回数据格式
#     """
#     def __init__(self, code=20000, message='成功', errors=None, data=None):
#         self.code = code
#         self.message = message
#         self.errors = {} if errors is None else errors
#         self.data = [] if data is None else data
#
#     def dict(self):
#         return {
#             'code': self.code,
#             'message': self.message,
#             'errors': self.errors,
#             'data': self.data
#         }
#
#
# class CustomModelViewSet(viewsets.ModelViewSet):
#     """
#     ModelViewSet 使用自定义数据格式返回
#     """
#
#     def create(self, request, *args, **kwargs):
#         response = super().create(request, *args, **kwargs)
#         return Response(ReturnMsg(data=response.data).dict())
#
#     def retrieve(self, request, *args, **kwargs):
#         response = super().retrieve(request, *args, **kwargs)
#         return Response(ReturnMsg(data=response.data).dict())
#
#     def update(self, request, *args, **kwargs):
#         response = super().update(request, *args, **kwargs)
#         return Response(ReturnMsg(data=response.data).dict())
#
#     def destory(self, request, *args, **kwargs):
#         response = super().destory(request, *args, **kwargs)
#         return Response(ReturnMsg().dict())
#
#     def list(self, request, *args, **kwargs):
#         response = super().list(request, *args, **kwargs)
#         return Response(ReturnMsg(data=response.data).dict())


# class CustomListModelSet(mixins.ListModelMixin):
#     """
#     ModelViewSet 使用自定义ListModel数据格式返回
#     """
#     def list(self, request, *args, **kwargs):
#         response = super().list(request, *args, **kwargs)
#         return Response(ReturnMsg(data=response.data).dict())


# class TasksViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
class TasksViewSet(viewsets.ModelViewSet):
    """
        任务列表视图api,查询,排序,过滤
    """
    # queryset = Tasks.objects.all()
    serializer_class = TasksSerializer
    permission_classes = (IsAuthenticated,)
    # 过滤器,排序，模糊查询
    filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
    search_fields = ['subjects', 'status', 'sender']
    ordering_fields = '__all__'

    def get_queryset(self):
        user_groups = self.request.user.groups.all()
        if user_groups:
            group = user_groups[0].name
        else:
            group = 'nogroup'

        # 如果是dba,audit和超级用户,则显示全部,否则显示用户自己提交的数据
        # 如果用户没有设置组,则显示为空
        if group == 'dba' or group == 'audit' or self.request.user.is_superuser:
            return Tasks.objects.all().order_by('create_time')
        elif group == 'user':
            return Tasks.objects.filter(sender=self.request.user.email)
        else:
            return Tasks.objects.filter(sender='nogroup')


@api_view(['POST'])
def user_logout(request):
    """
    退出登录
    """
    return Response({
        'code': 20000,
        'data': 'success'
    })


@api_view(['GET'])
def user_info(request):
    """
    获取用户和角色信息
    /user/info/
    Headers:Authorization jwt r32fdsf2rfds32r3resafdasfeafdas23qfdasdfaf.edffdasfeasfdasfdsafdsafvcx.dasfdasfew
    """
    roles = []
    user = request.user
    user_groups = request.user.groups.all()
    if user_groups:
        roles.append(user_groups[0].name)
    else:
        roles.append('nogroup')

    return Response({
        'name': user.username,
        'email': user.email,
        'roles': roles,
        'introduction': 'I am a super administrator',
        'avatar': 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif'
    })


@api_view(['POST'])
def audit(request):
    """
    审批处理
    """
    if request.method == 'POST':
        """
        处理post请求
        """
        # print(request.data)
        id = request.data.pop('id', None)
        status = request.data.pop('status', None)
        # 如果id和status都存在,则更新对应的数据
        if not id or not status:
            return Response({
                'message': '数据提交不完整!需要提交id和status'
            })

        try:
            # 更新审核状态
            task = Tasks.objects.get(id=id)
            task.status = status
            task.update_time = datetime.datetime.now()
            task.save()
        except:
            return Response({
                'message': '审核id不存在或其他错误!'
            })

        # pass通过 reject 拒绝
        if status == 'PASS':
            return Response({
                'message': '审批通过!'
            })
        else:
            return Response({
                'message': '审批拒绝!'
            })


@api_view(['GET'])
def task_exec(request, *args, **kwargs):
    """
    执行任务
    """
    # todo 1.获取执行任务的id
    taskid = kwargs['id']
    task = Tasks.objects.get(id=taskid)

    # todo 2.执行export任务
    result = export.delay(task.svn_address, task.subjects)
    result_object = AsyncResult(id=result.id)

    print('result_object.status=====> ', result_object.status)
    if result_object.status == 'PENDING':
        # todo: 3.更新任务状态
        task.task_id = result.id
        task.task_status = result_object.status
        task.save()
        return Response({'message': '任务执行成功!'})
    elif result_object.status == 'SUCCESS':
        # todo: 4.更新任务状态
        task.task_id = result.id
        task.task_status = 'SUCCESS'
        task.task_result = result_object.result
        task.save()
        create_zip
        return Response({'message': '任务执行成功!'})
    elif result_object.status == 'FAILURE':
        return Response({'message': '任务执行失败!'})
    else:
        return Response({'message': '任务执行失败!'})


# 查看任务执行状态
@api_view(['GET'])
def task_status(request, *args, **kwargs):
    id = kwargs['id']
    task = Tasks.objects.get(id=id)
    taskid = task.task_id
    result_object = AsyncResult(id=taskid)

    print('result_object.status=====> ', result_object.status)

    if result_object.status == 'PENDING':
        return Response({'message': '任务执行中...'})
    elif result_object.status == 'SUCCESS':

        # 压缩文件
        task_dir = "F:\\django\\data-service-backend\\export\\task"
        zip_source = os.path.join(task_dir, task.subjects)
        zipname = create_zip(zip_source, task.subjects)

        # todo 更新任务状态
        task.task_status = 'SUCCESS'
        task.task_result = zipname
        task.save()

        return Response({'message': '任务执行成功!'})
    elif result_object.status == 'FAILURE':
        # todo 更新任务状态
        task.task_status = 'FAILURE'
        task.save()

        return Response({'message': '任务执行失败!'})
    else:
        return Response({'message': '任务执行失败!'})


# 文件下载
@api_view(['GET'])
def task_down(request, *args, **kwargs):
    id = kwargs['id']
    task = Tasks.objects.get(id=id)
    file_path = task.task_result
    file_name = os.path.basename(file_path)

    if not os.path.isfile(file_path):  # 判断下载文件是否存在
        return Response({'message': '下载文件不存在!'})

    def file_iterator(fp, chunk_size=512):
        """
        文件生成器,防止文件过大，导致内存溢出
        :param fp: 文件绝对路径
        :param chunk_size: 块大小
        :return: 生成器
        """
        with open(fp, mode='rb') as f:
            while True:
                c = f.read(chunk_size)
                if c:
                    yield c
                else:
                    break

    try:
        # 设置响应头
        # StreamingHttpResponse将文件内容进行流式传输，数据量大可以用这个方法
        # print(file_path)
        # print(file_name)
        response = StreamingHttpResponse(file_iterator(file_path))
        # 以流的形式下载文件,这样可以实现任意格式的文件下载
        response['Content-Type'] = 'application/octet-stream'
        # Content-Disposition就是当用户想把请求所得的内容存为一个文件的时候提供一个默认的文件名
        # 避免中文乱码
        response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path(file_name))
        # response.setHeader("Access-Control-Expose-Headers", "Content-Disposition")
        return response
    except Exception as e:
        print(e)
        return Response({'message': '下载出错!'})


@api_view(['GET'])
def task_dashboard(request, *args, **kwargs):
    """
    首页图表展示
    """
    # 总任务数
    total = Tasks.objects.all().count()
    # 执行成功的
    success = Tasks.objects.filter(task_status='SUCCESS').count()
    # 已审计的
    audit = Tasks.objects.filter(task_status__isnull=False).count()
    # 执行失败的
    failure = Tasks.objects.filter(task_status='FAILURE').count()
    # 已执行的
    execute = total - success - failure

    return Response({
            'total': total,
            'success': success,
            'audit': audit,
            'execute': execute,
            'failure': failure
    })
